001 /*
002 * Copyright 2005 Stephen J. McConnell
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
013 * implied.
014 *
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 package net.dpml.library.impl;
020
021 import java.util.ArrayList;
022 import java.util.Enumeration;
023 import java.util.Properties;
024
025 import net.dpml.library.Dictionary;
026 import net.dpml.library.info.AbstractDirective;
027
028 import net.dpml.util.PropertyResolver;
029
030 /**
031 * Utility class used for construction of a module model from an XML source.
032 *
033 * @author <a href="http://www.dpml.net">The Digital Product Meta Library</a>
034 * @version 1.0.0
035 */
036 public class DefaultDictionary implements Dictionary
037 {
038 private final DefaultDictionary m_parent;
039 private final AbstractDirective m_directive;
040 private final Properties m_properties;
041
042 /**
043 * Creation of a new dictionary. The dictionary provides support
044 * for property inheritance within the hierachy of of modules based
045 * an a single root virtual module. When handling a propety request
046 * the dictionary will attempt to resolve the property value using
047 * local property values. If the value is unresolved, the implemenetation
048 * will attempt to delegate the request to a parent dictionary if available.
049 *
050 * @param parent the parent dictionary (possibly null)
051 * @param directive an abstract directive containing local properties
052 */
053 public DefaultDictionary( DefaultDictionary parent, AbstractDirective directive )
054 {
055 if( null == directive )
056 {
057 throw new NullPointerException( "directive" );
058 }
059 m_parent = parent;
060 m_directive = directive;
061
062 Properties properties = getParentProperties();
063 m_properties = new Properties( properties );
064 Properties local = directive.getProperties();
065 String[] keys = getLocalPropertyNames( local );
066 for( int i=0; i<keys.length; i++ )
067 {
068 String key = keys[i];
069 String value = local.getProperty( key );
070 m_properties.setProperty( key, value );
071 }
072 }
073
074 //----------------------------------------------------------------------------
075 // Dictionary
076 //----------------------------------------------------------------------------
077
078 /**
079 * Return the property names associated with the dictionary.
080 * @return the array of property names
081 */
082 public String[] getPropertyNames()
083 {
084 return getLocalPropertyNames( m_properties );
085 }
086
087 /**
088 * Return the local property names associated with the dictionary.
089 * @return the array of local property names
090 */
091 public String[] getLocalPropertyNames()
092 {
093 return getLocalPropertyNames( m_directive.getProperties() );
094 }
095
096 /**
097 * Return a property value.
098 * @param key the property key
099 * @return the property value
100 */
101 public String getProperty( String key )
102 {
103 return getProperty( key, null );
104 }
105
106 /**
107 * Return a property value.
108 * @param key the property key
109 * @param value the default value
110 * @return the property value
111 */
112 public String getProperty( String key, String value )
113 {
114 String result = m_properties.getProperty( key, value );
115 return resolve( result );
116 }
117
118 /**
119 * Return an integer property value.
120 * @param key the property key
121 * @param value the default value
122 * @return the property value as an integer
123 * @exception NumberFormatException if underlying property value
124 * cannot be resolved to an integer
125 */
126 public int getIntegerProperty( String key, int value )
127 {
128 String result = m_properties.getProperty( key );
129 if( null == result )
130 {
131 return value;
132 }
133 else
134 {
135 String literal = resolve( result );
136 return Integer.parseInt( literal );
137 }
138 }
139
140 /**
141 * Return an boolean property value.
142 * @param key the property key
143 * @param value the default value
144 * @return the property value as an boolean
145 * @exception NumberFormatException if underlying property value
146 * cannot be resolved to an integer
147 */
148 public boolean getBooleanProperty( String key, boolean value )
149 {
150 String result = m_properties.getProperty( key );
151 if( null != result )
152 {
153 return Boolean.valueOf( result ).booleanValue();
154 }
155 else
156 {
157 return value;
158 }
159 }
160 /**
161 * Evaluate and expand any symbolic references in the supplied value.
162 * @param value the value to resolve
163 * @return the resolved value
164 */
165 public String resolve( String value )
166 {
167 return PropertyResolver.resolve( m_properties, value );
168 }
169
170 //----------------------------------------------------------------------------
171 // internal
172 //----------------------------------------------------------------------------
173
174 void setProperty( String name, String value )
175 {
176 m_properties.setProperty( name, value );
177 }
178
179 AbstractDirective getAbstractDirective()
180 {
181 return m_directive;
182 }
183
184 Properties getProperties()
185 {
186 return m_properties;
187 }
188
189 private Properties getParentProperties()
190 {
191 if( null == m_parent )
192 {
193 return new Properties();
194 }
195 else
196 {
197 return m_parent.getProperties();
198 }
199 }
200
201 private String[] getLocalPropertyNames( Properties properties )
202 {
203 ArrayList list = new ArrayList();
204 Enumeration names = properties.propertyNames();
205 while( names.hasMoreElements() )
206 {
207 list.add( (String) names.nextElement() );
208 }
209 return (String[]) list.toArray( new String[0] );
210 }
211
212 Properties getExportProperties()
213 {
214 String[] keys = getLocalPropertyNames();
215 Properties properties = new Properties();
216 for( int i=0; i<keys.length; i++ )
217 {
218 String key = keys[i];
219 String value = getProperty( key );
220 properties.setProperty( key, value );
221 }
222 return properties;
223 }
224 }